<!DOCTYPE html>
<html>
<head>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  <title>The source code</title>
  <link href="../resources/prettify/prettify.css" type="text/css" rel="stylesheet" />
  <script type="text/javascript" src="../resources/prettify/prettify.js"></script>
  <style type="text/css">
    .highlight { display: block; background-color: #ddd; }
  </style>
  <script type="text/javascript">
    function highlight() {
      document.getElementById(location.hash.replace(/#/, "")).className = "highlight";
    }
  </script>
</head>
<body onload="prettyPrint(); highlight();">
  <pre class="prettyprint lang-js"><span id='global-property-'>/**
</span> * @ignore
 * collection of models
 * @author yiminghe@gmail.com
 */
KISSY.add(&quot;mvc/collection&quot;, function (S, Model, Base) {

    function findModelIndex(mods, mod, comparator) {
        var i = mods.length;
        if (comparator) {
            var k = comparator(mod);
            for (i = 0; i &lt; mods.length; i++) {
                var k2 = comparator(mods[i]);
                if (k &lt; k2) {
                    break;
                }
            }
        }
        return i;
    }

<span id='KISSY-MVC-Collection'>    /**
</span>     * Collection. A list of model.
     * @class KISSY.MVC.Collection
     * @extends KISSY.Base
     */
    return Base.extend({
<span id='KISSY-MVC-Collection-method-sort'>        /**
</span>         * Sort model list according {@link KISSY.MVC.Collection#comparator}.
         */
        sort: function () {
            var comparator = this.get(&quot;comparator&quot;);
            if (comparator) {
                this.get(&quot;models&quot;).sort(function (a, b) {
                    return comparator(a) - comparator(b);
                });
            }
        },

<span id='KISSY-MVC-Collection-method-toJSON'>        /**
</span>         * Get json representation of this collection.
         * @return Object[]
         */
        toJSON: function () {
            return S.map(this.get(&quot;models&quot;), function (m) {
                return m.toJSON();
            });
        },

<span id='KISSY-MVC-Collection-method-add'>        /**
</span>         * Add a model to current collection.
         * @param {Object|KISSY.MVC.Model} model Model or json data to be added.
         * @param {Object} [opts] Add config
         * @param {Function} opts.silent Whether to fire add event.
         */
        add: function (model, opts) {
            var self = this,
                ret = true;
            if (S.isArray(model)) {
                var orig = [].concat(model);
                S.each(orig, function (m) {
                    var t = self._add(m, opts);
                    ret = ret &amp;&amp; t;
                });
            } else {
                ret = self._add(model, opts);
            }
            return ret;
        },

<span id='KISSY-MVC-Collection-method-remove'>        /**
</span>         * Remove an existing model from current collection.
         * @param {KISSY.MVC.Model} model Model to be removed.
         * @param {Object} [opts] Remove config.
         * @param {Function} opts.silent Whether to fire remove event.
         */
        remove: function (model, opts) {
            var self = this;
            if (S.isArray(model)) {
                var orig = [].concat(model);
                S.each(orig, function (m) {
                    self._remove(m, opts);
                });
            } else if (model) {
                self._remove(model, opts);
            }
        },

<span id='KISSY-MVC-Collection-method-at'>        /**
</span>         * Get model at specified index.
         * @param {Number} i Specified index.
         */
        at: function (i) {
            return this.get(&quot;models&quot;)[i];
        },

        _normModel: function (model) {
            var ret = true;
            if (!(model instanceof Model)) {
                var data = model,
                    modelConstructor = this.get(&quot;model&quot;);
                model = new modelConstructor();
                ret = model.set(data, {
                    silent: 1
                });
            }
            return ret &amp;&amp; model;
        },

<span id='KISSY-MVC-Collection-method-load'>        /**
</span>         * Initialize model list by loading data using sync mechanism.
         * @param {Object} opts Load config.
         * @param {Function} opts.success Callback when load is successful.
         * @param {Function} opts.error Callback when error occurs on loading.
         * @param {Function} opts.complete Callback when load is complete.
         * @chainable
         */
        load: function (opts) {
            var self = this;
            opts = opts || {};
            var success = opts.success;
<span id='global-method-success'>            /**
</span>             * @ignore
             */
            opts.success = function (resp) {
                if (resp) {
                    var v = self.get(&quot;parse&quot;).call(self, resp);
                    if (v) {
                        self.set(&quot;models&quot;, v, opts);
                    }
                }
                // https://github.com/kissyteam/kissy/issues/138
                S.each(self.get(&quot;models&quot;), function (m) {
                    m.__isModified = 0;
                });
                success &amp;&amp; success.apply(this, arguments);
            };
            self.get(&quot;sync&quot;).call(self, self, 'read', opts);
            return self;
        },

<span id='KISSY-MVC-Collection-method-create'>        /**
</span>         * Add a model to current collection by provide json data.
         * @param {Object} model Json data represent model data.
         * @param {Object} opts Create config.
         * @param {Function} opts.success Callback when create is successful.
         * @param {Function} opts.error Callback when error occurs on creating.
         * @param {Function} opts.complete Callback when create is complete.
         * @param {Function} opts.silent Whether to fire add event.
         */
        create: function (model, opts) {
            var self = this;
            opts = opts || {};
            model = this._normModel(model);
            if (model) {
                model.addToCollection(self);
                var success = opts.success;
                opts.success = function () {
                    self.add(model, opts);
                    success &amp;&amp; success();
                };
                model.save(opts);
            }
            return model;
        },

        _add: function (model, opts) {
            model = this._normModel(model);
            if (model) {
                opts = opts || {};
                var index = findModelIndex(this.get(&quot;models&quot;), model, this.get(&quot;comparator&quot;));
                this.get(&quot;models&quot;).splice(index, 0, model);
                model.addToCollection(this);
                if (!opts['silent']) {
                    this.fire(&quot;add&quot;, {
                        model: model
                    });
                }
            }
            return model;
        },

<span id='KISSY-MVC-Collection-method-_remove'>        /**
</span>         * not call model.destroy ,maybe model belongs to multiple collections
         * @private
         */
        _remove: function (model, opts) {
            opts = opts || {};
            var index = S.indexOf(model, this.get(&quot;models&quot;));
            if (index != -1) {
                this.get(&quot;models&quot;).splice(index, 1);
                model.removeFromCollection(this);
            }
            if (!opts['silent']) {
                this.fire(&quot;remove&quot;, {
                    model: model
                });
            }
        },

<span id='KISSY-MVC-Collection-method-getById'>        /**
</span>         * Get model instance by id.
         * @param {String} id
         */
        getById: function (id) {
            var models = this.get(&quot;models&quot;);
            for (var i = 0; i &lt; models.length; i++) {
                var model = models[i];
                if (model.getId() === id) {
                    return model;
                }
            }
            return null;
        },

<span id='KISSY-MVC-Collection-method-getByCid'>        /**
</span>         * Get model instance by client id.
         * @param {String} cid Client id auto generated by model.
         */
        getByCid: function (cid) {
            var models = this.get(&quot;models&quot;);
            for (var i = 0; i &lt; models.length; i++) {
                var model = models[i];
                if (model.get(&quot;clientId&quot;) === cid) {
                    return model;
                }
            }
            return null;
        }

    }, {
        ATTRS: {
<span id='KISSY-MVC-Collection-property-model'>            /**
</span>             * Model constructor with in current collection.
             * @type {KISSY.MVC.Model}
             */
            model: {
                value: Model
            },
<span id='KISSY-MVC-Collection-property-models'>            /**
</span>             * Model list.
             * @type {KISSY.MVC.Model[]}
             */
            models: {
                /*
                 normalize model list
                 @param models
                 */
                setter: function (models) {
                    var prev = this.get(&quot;models&quot;);
                    this.remove(prev, {silent: 1});
                    this.add(models, {silent: 1});
                    return this.get(&quot;models&quot;);
                },
                value: []
            },
<span id='KISSY-MVC-Collection-property-url'>            /**
</span>             * Get url for sending data to server.
             * @type {String|Function}
             */
            url: {
                value: &quot;&quot;
            },
<span id='KISSY-MVC-Collection-property-comparator'>            /**
</span>             * Comparator function for index getter when adding model.
             * default to append to last of current model list.
             * @type {Function}
             */
            comparator: {},
<span id='KISSY-MVC-Collection-property-sync'>            /**
</span>             * Sync function to sync data with server.
             * Default to call {@link KISSY.MVC#sync}
             * @type {Function}
             */
            sync: {
                value: function () {
                    S.require(&quot;mvc&quot;).sync.apply(this, arguments);
                }
            },
<span id='KISSY-MVC-Collection-property-parse'>            /**
</span>             * Get structured data from raw data returned from server.
             * default to return raw data from server.
             * @type {Function}
             */
            parse: {
                value: function (resp) {
                    return resp;
                }
            }
        }
    });
}, {
    requires: ['./model', 'base']
});</pre>
</body>
</html>
